#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#      This file is distributed as part of the WebAMP2 project and is licensed
#      under the GPL version 2.
#
#      Copyright 2007 Chris Seickel <cseickel@gmail.com>
#
#      This program is free software; you can redistribute it and/or modify
#      it under the terms of the GNU General Public License version 3 as published by
#      the Free Software Foundation.
#
#      This program is distributed in the hope that it will be useful,
#      but WITHOUT ANY WARRANTY; without even the implied warranty of
#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#      GNU General Public License version 3 for more details.
#
#      You should have received a copy of the GNU General Public License version 3
#      along with this program; if not, write to:
#       Free Software Foundation, Inc.
#       51 Franklin Street, Fifth Floor
#       Boston, MA 02110-1301, USA

import cherrypy
import string
from mpd import *
from time import sleep
import codecs
import pickle
import os
import sys
import glob
import urllib2
import zipfile
import socket
import fcntl
import struct
import local_ip
import findlyrics
cherrypy.config.update("global.conf")
cherrypy.config["tools.staticdir.root"] = os.getcwd()

# Validates ip address and attempts to determine the correct one
# if it is blank or fails validation
srv = "http://"+local_ip.getipaddr(cherrypy.server.socket_host)
srv += ":"+str(cherrypy.server.socket_port)
    
static = os.path.join(os.getcwd(), "static")
# Initialize player.
player = Player(cherrypy.config.get("mpd_host"),cherrypy.config.get("mpd_port"), 
                dbDir=os.path.join(static,"rdf"), dbFile=cherrypy.config.get("mpd_db"),
                base_url=srv)
player.init()


def rdf():
    path = cherrypy.request.path_info.split("/")
    if len(path) > 3:
        if path[0:3] == ["","static","rdf"]:
            mytype = path[3]
        if mytype == "dirs":
            dir = path[4].split("-")[0]
            fname = static+"/rdf/dirs/%s-%s.xml" % (dir, player.dbVer)
            if not os.path.exists(fname):
                db = player.db.createRDF_dir(dir, fname)
                
        elif mytype == "artists":
            artist = path[4].split("-")[0]
            fname = static+"/rdf/artists/%s-%s.xml" % (artist, player.dbVer)
            if not os.path.exists(fname):
                player.db.createRDF_artist(artist, fname)
                
        elif mytype == "albums":
            album = path[4].split("-")[0]
            fname = static+"/rdf/albums/%s-%s.xml" % (album, player.dbVer)
            if not os.path.exists(fname):
                player.db.createRDF_album(album, fname)
        
        elif mytype == "covers":
            album = path[4][0:-4]
            fname = static+"/rdf/covers/%s.jpg" % album
            alt = static+"/blank.jpg"
            if not os.path.exists(fname):
                player.db.getCover(album, fname, alt)
                
        elif mytype == "playlists.xml":
            player.getPlaylist(id=0)
            
        elif mytype == "playlists":
            id = int(path[4].split("-")[0])
            fname = static+"/rdf/playlists/%d-%s.xml" % (id, player.dbVer)
            print id
            player.getPlaylist(id, fname)
        
        return False
            
        
cherrypy.tools.rdf = cherrypy._cptools.HandlerTool(rdf)
cherrypy.config['tools.rdf.on'] = True


class Root:    
        
    @cherrypy.expose 
    def index(self):
        p = static+"/index.html"
        print p
        f = open(p,"r")
        page = string.join(f.readlines())
        f.close()
        return page
    
    def makeRange(self, val):
        rng = []
        R = val.split("and")
        for subR in R:
            r = subR.split("to")
            if (len(r) == 2):
                rng += range(int(r[0]), int(r[1])+1)
            else:
                rng.append(int(r[0]))
        return rng
    
    @cherrypy.expose
    def webamp2xul(self):
        h = "application/x-xpinstall"
        cherrypy.response.headers['Content-Type'] = h
        mainjs = open(static+"/xul/content/common.js", mode="r")
        lines = mainjs.readlines()
        lines[0] = "var base='%s'\n" % srv
        mainjs.close()
        mainjs = open(static+"/xul/content/common.js", mode="w")
        mainjs.writelines(lines)
        mainjs.close()
        xpi = static+"/webamp2.xpi"
        print "Creating XPI package"
        z = zipfile.ZipFile(xpi, mode="w",
                            compression=zipfile.ZIP_STORED)
        for dirpath,dirs,files in os.walk(static+"/xul"):
            for a_file in files:
                real_path = os.path.join(dirpath, a_file)
                my_path = real_path.replace(static+"/xul", "")
                if (real_path.find("svn")+real_path.find("~")) < 0:
                    print "add to xpi: ", my_path
                    z.write(real_path,my_path)
        z.close()
        return open(xpi, mode="rb")
                
    @cherrypy.expose
    def dbversion(self):
        cherrypy.response.headers['Content-Type'] = 'text/plain'
        return player.dbVer
    
    @cherrypy.expose
    def updates(self):
        cherrypy.response.headers['Content-Type'] = 'text/plain'
        me = cherrypy.request.headers["Remote-Addr"]
        player.keepAlive = 30
        if not player.connected: player.start_poller()
        i = 0
        s = ""
        if not js.queue.has_key(me):
            s = "initMe('%s');newDB('%s')" % (me, player.dbVer)
            js.addClient(me, slots=js.slots, init=[s])
            print "CLIENT %s CONNECTED (forced)" % me
        while (i < 100 and js.queue.has_key(me)):
            player.keepAlive = 30
            s = js.nextInQueue(me)
            if len(s) > 0:
                i = 100
            else:
                i +=1
                sleep(0.1)
        print "Sending script:  "+s
        return s
    
    @cherrypy.expose
    def connect(self, **kw):
        me = cherrypy.request.headers["Remote-Addr"]
        onPort = int(kw.get("port", 8008))
        player.keepAlive = 300
        if not player.connected: player.start_poller()
        s = "['setDB', '%s']" % player.dbVer
        if js.connect(me, onPort, init=s):
            print "CLIENT %s CONNECTED" % me
            return "OK"
        else:
            print "Port already in use on that ip."
            return "PORT_BUSY"
    
    
    @cherrypy.expose
    def disconnect(self, **kw):
        me = cherrypy.request.headers["Remote-Addr"]
        onPort = int(kw.get("port", 8008))
        js.disconnect(me, onPort)
        return "OK"
    
        
    @cherrypy.expose
    def doCommand(self, **kw):
        action = kw.get("action", None)
        if action == "playpause": 
            if obs_state.value == "play":
                player.pause(True)
            elif obs_state.value == "pause":
                player.pause(False)
            else:
                player.play()
        elif action == "play":
            song = kw.get("val", None)
            player.play(song)
        elif action == "prev": player.previous()
        elif action == "stop": player.stop()
        elif action == "next": player.next()
        elif action == "vol":
            val = int(kw.get("val", 0))
            player.volumeSet(val)
        elif action == "seek":  
            val = int(kw.get("val", 0))
            player.seek(val)
        elif action == "addfile" or action == "add":  
            val = kw.get("val", 0)
            rng = self.makeRange(val)
            player.playlistAppend(rng)
        elif action == "adddir":  
            val = kw.get("val", 0)
            rng = self.makeRange(val)
            player.playlistAppend(rng, mytype="dir")
        elif action == "addart":  
            val = kw.get("val", 0)
            rng = self.makeRange(val)
            player.playlistAppend(rng, mytype="artist")
        elif action == "addalb":  
            val = kw.get("val", 0)
            rng = self.makeRange(val)
            player.playlistAppend(rng, mytype="album")
        elif action == "addpls":  
            val = kw.get("val", 0)
            rng = self.makeRange(val)
            player.playlistLoad(rng)
        elif action == "remove":
            val = kw.get("val", "")
            rng = self.makeRange(val)
            player.playlistRemove(rng)
        elif action == "clear":
            player.playlistClear()
        elif action == "save":
            val = kw.get("val", "")
            player.playlistSave(val)
        elif action == "shuffle":
            player.shuffle()
        elif action == "random":
            player.random()
        elif action == "repeat":
            player.repeat()
        elif action == "update":
            player.update()
        return "OK"    

    @cherrypy.expose
    def search(self, **kw):
        what = kw.get('what', '')
        if len(what) < 2: return ''
        where = kw.get('where', 'any')
        res = player.db.search(what, where)
        res = "["+",".join(res)+"]"
        print res
        return res
        
    @cherrypy.expose
    def playlist_ids(self):
        cherrypy.response.headers['Content-Type'] = 'text/plain'
        return u'PlaylistIDs={' + u', '.join(player.playlistIDs()) + '}'
    
    @cherrypy.expose
    def playlist_rdf(self):
        cherrypy.response.headers['Content-Type'] = 'text/plain'
        return player.createRDFplaylist()

    @cherrypy.expose
    def prepDir(self, **kw):
        dir = kw.get("dir", None)
        artist = kw.get("artist", None)
        album = kw.get("album", None)
        if dir:
            fname = static+"/rdf/dirs/%s-%s.xml" % (dir, player.dbVer)
            if not os.path.exists(fname):
                db = player.db.createRDF_dir(dir)
                old_files = glob.glob(static+"/rdf/dirs/%s*" % dir)
                for old_file in old_files:
                    os.remove(old_file)
                f = codecs.open(fname, "wt",'utf-8')
                f.write(db)
                f.close()
        elif artist:
            fname = static+"/rdf/artists/%s-%s.xml" % (artist, player.dbVer)
            if not os.path.exists(fname):
                db = player.db.createRDF_artist(artist)
                old_files = glob.glob(static+"/rdf/artists/%s*" % artist)
                for old_file in old_files:
                    os.remove(old_file)
                f = codecs.open(fname, "wt",'utf-8')
                f.write(db)
                f.close()
        elif album:
            fname = static+"/rdf/albums/%s-%s.xml" % (album, player.dbVer)
            if not os.path.exists(fname):
                db = player.db.createRDF_album(album)
                old_files = glob.glob(static+"/rdf/albums/%s*" % artist)
                for old_file in old_files:
                    os.remove(old_file)
                f = codecs.open(fname, "wt",'utf-8')
                f.write(db)
                f.close()
        else: return "ERROR"
        return "OK"
    
    @cherrypy.expose
    def song_info(self, **kw):
        """Borrowed from MPD WebAMP, this is temporary."""
        id = kw.get("id", "")
        if id == "":
            cur_song = obs_curSong.value
        else:
            cur_song = player.db.getSong(id)
        print cur_song
        f = findlyrics.Song(cur_song)
        f.search()
        np = f.SearchResults.parse(0).table
        rc = f.SearchResults.count
        if (rc > 1):
            alt = "<br><div style='padding:10px'><b>Full Lyrics Search Results:</b><br><br>"
            for i in range(0, rc-1):
                alt += "<a href='javascript:getNowPlaying(\""+f.SearchResults.links[i]+"\")'>"
                alt += f.SearchResults.labels[i]+"</a><br>"
            alt += "</div>"
            np += alt
        np += "<div style='padding:10px;color:#555'>"
        np += "Lyrics by Findlyrics.com, Similar Artists by last.fm, "
        np += "album art courtesy of amazon.com using MusicBrainz.com metadata.</div>"
        head = """<html><head>
        <style type='text/css'>
        body {background-color: black;color: #EFEFEF;font-family: "Bitstream Vera Sans" "Verdana";}
        a:link{color: #B9B9B9;text-decoration: underline;font-weight: bold;font-style: normal;}
        a:hover{color: white;text-decoration: underline;font-weight: bold;font-style: normal;}
        a:visited{color: white;text-decoration: underline;font-weight: bold;font-style: normal;}
        a:active{color: #AAAAAA;text-decoration: underline;font-weight: bold;font-style: normal;}
        Table {border-collapse: collapse;width: 97%;margin-top: 5px;margin-left: auto;margin-right: auto;}
        TD {vertical-align: top;padding: 1px 2px 1px 2px}
        .art {width: 240px;height: 240px;display: table-cell;vertical-align: middle;background-color: #0A0A0A;border: 1px solid #222222;}
        #SimlarArtists {margin-top: 20px;padding: 10px;width: 220px;text-align: left;background-color: #0A0A0A;border: 1px solid #222222;}
        .similar {padding-top: 5px;}
        .NPitem {position: absolute;left: 90px;}
        </style>
        </head><body>"""
        return head+np+"</body></html>"


if player.ready:
    from client_interface import *
    cherrypy.quickstart(Root(),"",'WebAMP2.conf')
    js.stop()
    player.keepAlive=0
